<?php

declare(strict_types=1);

use core\{DB, Session, Flash, Url};

/**
 * 获取一个数据表操作对象
 * 
 * @param  string $table  数据表名称
 * @param  string $item   默认 db , 对应的数据库一级2配置名称
 * @return object         数据库操作对象
 */
function db($table, $item = 'db')
{
    $conf = config($item);
    return DB::getInstance($conf, $table, $item);
}


/**
 * 功能 : 获取一个模型
 * @param  string $modelName  模型名称
 * @return object             模型对象
 */
function model($name)
{
    $modelName = '\\app\\models\\' . $name;
    if (class_exists($modelName)) {
        $model = new $modelName();
        return $model;
    } else {
        throw new Exception("模型 {$modelName} 不存在");
    }
}


/**
 * 加载视图
 *
 * @param  string $path  视图文件名
 * @param  array  $data  分配的变量
 * @return string
 */
function view(string $path, array $data = []): string
{
    $file = VIEW_PATH . $path . '.view.php';

    if (!file_exists($file)) {
        throw new Exception("模板文件 {$file} 不存在");
    }

    if ($data && is_array($data)) {
        foreach ($data as $key => $value) {
            $$key = $value;
            $data[$key] = escape($value);
        }
        extract($data, EXTR_SKIP);
    }

    ob_start();
    include $file;
    $contents = ob_get_contents() ?: '';
    ob_end_flush();

    return $contents;
}


/**
 * 读取配置
 */
function config($key = null)
{
    static $conf = null;

    if ($conf === null) {
        $conf = require APP_PATH . '/config.php';
    }

    if (is_null($key)) {
        return $conf;
    }

    if (strstr($key, '.') !== '') {
        $keys = explode('.', $key);
        if (empty($keys[1])) {
            return $conf[$keys[0]];
        }

        return $conf[$keys[0]][$keys[1]];
    }

    return $conf[$key];
}

/**
 * 消毒数据
 *
 * @param  string $data
 * @return string
 */
function sanitize(string $data): string
{
    $data = trim($data);
    $data = escape($data);
    
    return $data;
}

/**
 * 返回当前客户端 IP
 */
function getIp()
{
    $client_ip = filter_var($_SERVER['HTTP_CLIENT_IP'] ?? '', FILTER_VALIDATE_IP);
    $forwarded = filter_var($_SERVER['HTTP_X_FORWARDED_FOR'] ?? '', FILTER_VALIDATE_IP);

    if (!empty($client_ip)) {
        return $client_ip;
    } elseif (!empty($forwarded)) {
        return $forwarded;
    }

    return $_SERVER['REMOTE_ADDR'] ?? '';
}

/**
 * 过滤 html
 */
function escape(string $string, $raw = false)
{
    if (!$raw) {
        return htmlspecialchars($string, ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8');
    } else {
        return $string;
    }
}


function flash(string $name = '', string $message = '')
{
    Flash::add($name, $message);
}

function redirect(string $path, int $code = 303)
{
    header('location: ' . $path, true, $code);
}

function session(string $key)
{
    return Session::has($key) ? Session::get($key) : false;
}

function csrf_token(int $length = 32)
{
    return Session::getToken($length);
}

function url(string $str = ''): string
{
    return Url::home() . filter_var($str, FILTER_SANITIZE_URL);
}

function isLogged(): bool
{
    return Session::has('user_id');
}

/**
 * 输出 json
 */
function json(string $msg, string $status = 'error')
{
    // header('Content-Type: application/json; charset=utf-8');
    echo json_encode(
        [
            'message' => escape($msg),
            'status'  => $status
        ],
        JSON_UNESCAPED_UNICODE
    );
}

/**
 * 检查请求方法是否为 ajax
 *
 * @return boolean
 */
function isAjax(): bool
{
    return (isset($_SERVER['HTTP_X_REQUESTED_WITH']) && strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) == 'xmlhttprequest');
}

/**
 * 检测是否使用手机访问
 * 
 * @return bool
 */
function isMobile(): bool
{
    if (isset($_SERVER['HTTP_VIA']) && stristr($_SERVER['HTTP_VIA'], "wap")) {
        return true;
    } elseif (isset($_SERVER['HTTP_ACCEPT']) && strpos(strtoupper($_SERVER['HTTP_ACCEPT']), "VND.WAP.WML")) {
        return true;
    } elseif (isset($_SERVER['HTTP_X_WAP_PROFILE']) || isset($_SERVER['HTTP_PROFILE'])) {
        return true;
    } elseif (isset($_SERVER['HTTP_USER_AGENT']) && preg_match('/(blackberry|configuration\/cldc|hp |hp-|htc |htc_|htc-|iemobile|kindle|midp|mmp|motorola|mobile|nokia|opera mini|opera |Googlebot-Mobile|YahooSeeker\/M1A1-R2D2|android|iphone|ipod|mobi|palm|palmos|pocket|portalmmm|ppc;|smartphone|sonyericsson|sqh|spv|symbian|treo|up.browser|up.link|vodafone|windows ce|xda |xda_)/i', $_SERVER['HTTP_USER_AGENT'])) {
        return true;
    } else {
        return false;
    }
}



/**
 * 打印变量
 */
function dump($value)
{
    echo '<pre>';
    var_dump($value);
    echo '</pre>';
}

/**
 * 页面不存在
 */
function pageNotFound()
{
    header('HTTP/1.1 404 Not Found');
    include CORE_PATH . 'templates/404.php';
}

/**
 * 规划缓存命名
 * 
 * @param  string  $name      缓存名称
 * @param  mixed   $parameter 缓存影响参数
 * @param  boolean $isSuper   是否为全局缓存
 * @return string 缓存名称
 */
function setCacheName($name, $parameter = '', $isSuper = true)
{
    $cacheConfig = config('cache');
    $parameter   = is_array($parameter) ? implode('_', $parameter) : $parameter;
    $cacheName   = $isSuper ? $cacheConfig['pre'] . $name . $parameter : $cacheConfig['pre'] . 'PG_C' . '_' . 'PG_M' . '_' . $name . $parameter;
    if (empty($cacheConfig['name2md5'])) {
        return $cacheName;
    }
    return md5($cacheName);
}
